//
//  STPPaymentHandler.h
//  StripeiOS
//
//  Created by Cameron Sabol on 5/10/19.
//  Copyright © 2019 Stripe, Inc. All rights reserved.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@class STPAPIClient;
@class STPPaymentIntent;
@class STPPaymentIntentParams;
@class STPSetupIntent;
@class STPSetupIntentConfirmParams;
@class STPThreeDSCustomizationSettings;
@protocol STPAuthenticationContext;

/**
 `STPPaymentHandlerActionStatus` represents the possible outcomes of requesting an action by `STPPaymentHandler`. An action could be confirming and/or handling the next action for a PaymentIntent.
 */
typedef NS_ENUM(NSInteger, STPPaymentHandlerActionStatus) {
    /**
     The action succeeded.
     */
    STPPaymentHandlerActionStatusSucceeded,

    /**
     The action was cancelled by the cardholder/user.
     */
    STPPaymentHandlerActionStatusCanceled,

    /**
     The action failed. See the error code for more details.
     */
    STPPaymentHandlerActionStatusFailed,
} NS_SWIFT_NAME(STPPaymentHandler.ActionStatus);

/**
 The error domain for errors in `STPPaymentHandler`.
 */
FOUNDATION_EXPORT NSString * const STPPaymentHandlerErrorDomain;

/**
 Error codes generated by `STPPaymentHandler`
 */
typedef NS_ERROR_ENUM(STPPaymentHandlerErrorDomain, STPPaymentHandlerErrorCode) {
    /**
     Indicates that the action requires an authentication method not recognized or supported by the SDK.
     */
    STPPaymentHandlerUnsupportedAuthenticationErrorCode NS_SWIFT_NAME(unsupportedAuthentication),

    /**
     Attach a payment method to the PaymentIntent or SetupIntent before using `STPPaymentHandler`.
     */
    STPPaymentHandlerRequiresPaymentMethodErrorCode NS_SWIFT_NAME(requiresPaymentMethod),

    /**
     The PaymentIntent or SetupIntent status cannot be resolved by `STPPaymentHandler`.
     */
    STPPaymentHandlerIntentStatusErrorCode NS_SWIFT_NAME(intentStatus),

    /**
     The action timed out.
     */
    STPPaymentHandlerTimedOutErrorCode NS_SWIFT_NAME(timedOut),

    /**
     There was an error in the Stripe3DS2 SDK.
     */
    STPPaymentHandlerStripe3DS2ErrorCode NS_SWIFT_NAME(stripe3DS2),

    /**
     The transaction did not authenticate (e.g. user entered the wrong code).
     */
    STPPaymentHandlerNotAuthenticatedErrorCode NS_SWIFT_NAME(notAuthenticated),

    /**
     `STPPaymentHandler` does not support concurrent actions.
     */
    STPPaymentHandlerNoConcurrentActionsErrorCode NS_SWIFT_NAME(noConcurrentActions),

    /**
     Payment requires a valid `STPAuthenticationContext`.  Make sure your presentingViewController isn't already presenting.
     */
    STPPaymentHandlerRequiresAuthenticationContextErrorCode NS_SWIFT_NAME(requiresAuthenticationContext),
    
    /**
     There was an error confirming the Intent.
     
     Inspect the `paymentIntent.lastPaymentError` or `setupIntent.lastSetupError` property.
     */
    STPPaymentHandlerPaymentErrorCode NS_SWIFT_NAME(payment),

    /**
     The provided PaymentIntent of SetupIntent client secret does not match the expected pattern for client secrets.

     Make sure that your server is returning the correct value and that is being passed to `STPPaymentHandler`.
     */
    STPPaymentHandlerInvalidClientSecret NS_SWIFT_NAME(invalidClientSecret),

} NS_SWIFT_NAME(STPPaymentHandlerError);


/**
 Completion block typedef for use in `STPPaymentHandler` methods for Payment Intents.
 */
typedef void (^STPPaymentHandlerActionPaymentIntentCompletionBlock)(STPPaymentHandlerActionStatus status, STPPaymentIntent * _Nullable paymentIntent, NSError * _Nullable error);

/**
 Completion block typedef for use in `STPPaymentHandler` methods for Setup Intents.
 */
typedef void (^STPPaymentHandlerActionSetupIntentCompletionBlock)(STPPaymentHandlerActionStatus status, STPSetupIntent * _Nullable setupIntent, NSError * _Nullable error);

/**
 `STPPaymentHandler` is a utility class that confirms PaymentIntents/SetupIntents and handles any authentication required, such as 3DS1/3DS2 for Strong Customer Authentication.
 It can present authentication UI on top of your app or redirect users out of your app (to e.g. their banking app).

 @see https://stripe.com/docs/mobile/ios/authentication
 */
NS_EXTENSION_UNAVAILABLE("STPPaymentHandler is not available in extensions")
@interface STPPaymentHandler : NSObject

/**
 The globally shared instance of `STPPaymentHandler`.
 */
+ (instancetype)sharedHandler;

/**
 `STPPaymentHandler` should not be directly initialized.
 */
- (instancetype)init NS_UNAVAILABLE;

/**
 By default `sharedHandler` initializes with [STPAPIClient sharedClient].
 */
@property (nonatomic) STPAPIClient *apiClient;

/**
 Customizable settings to use when performing 3DS2 authentication.
 
 Note: Configure this before calling any methods.
 Defaults to `[STPThreeDSCustomizationSettings defaultSettings]`.
 */
@property (nonatomic) STPThreeDSCustomizationSettings *threeDSCustomizationSettings;

/**
 Confirms the PaymentIntent with the provided parameters and handles any `nextAction` required
 to authenticate the PaymentIntent.
 
 Call this method if you are using automatic confirmation.  @see https://stripe.com/docs/payments/payment-intents/ios
 
 @param paymentParams The params used to confirm the PaymentIntent. Note that this method overrides the value of `paymentParams.useStripeSDK` to `@YES`.
 @param authenticationContext The authentication context used to authenticate the payment.
 @param completion The completion block. If the status returned is `STPPaymentHandlerActionStatusSucceeded`, the PaymentIntent status will always be either STPPaymentIntentStatusSucceeded or STPPaymentIntentStatusRequiresCapture if you are using manual capture. In the latter case, capture the PaymentIntent to complete the payment.
 */
- (void)confirmPayment:(STPPaymentIntentParams *)paymentParams
withAuthenticationContext:(id<STPAuthenticationContext>)authenticationContext
            completion:(STPPaymentHandlerActionPaymentIntentCompletionBlock)completion
NS_SWIFT_NAME(confirmPayment(withParams:authenticationContext:completion:));

/**
 Handles any `nextAction` required to authenticate the PaymentIntent.
 
 Call this method if you are using manual confirmation.  @see https://stripe.com/docs/payments/payment-intents/ios
 
 @param paymentIntentClientSecret The client secret of the PaymentIntent to handle next actions for.
 @param authenticationContext The authentication context used to authenticate the payment.
 @param returnURL An optional URL to redirect your customer back to after they authenticate or cancel in a webview. This should match the returnURL you specified during PaymentIntent confirmation.
 @param completion The completion block. If the status returned is `STPPaymentHandlerActionStatusSucceeded`, the PaymentIntent status will always be either STPPaymentIntentStatusSucceeded, or STPPaymentIntentStatusRequiresConfirmation, or STPPaymentIntentStatusRequiresCapture if you are using manual capture. In the latter two cases, confirm or capture the PaymentIntent on your backend to complete the payment.
 */
- (void)handleNextActionForPayment:(NSString *)paymentIntentClientSecret
         withAuthenticationContext:(id<STPAuthenticationContext>)authenticationContext
                         returnURL:(nullable NSString *)returnURL
                        completion:(STPPaymentHandlerActionPaymentIntentCompletionBlock)completion
NS_SWIFT_NAME(handleNextAction(forPayment:authenticationContext:returnURL:completion:));

/**
 Confirms the SetupIntent with the provided parameters and handles any `nextAction` required
 to authenticate the SetupIntent.
 
 @see https://stripe.com/docs/payments/cards/saving-cards#saving-card-without-payment
 
 @param setupIntentConfirmParams The params used to confirm the SetupIntent. Note that this method overrides the value of `setupIntentConfirmParams.useStripeSDK` to `@YES`.
 @param authenticationContext The authentication context used to authenticate the SetupIntent.
 @param completion The completion block. If the status returned is `STPPaymentHandlerActionStatusSucceeded`, the SetupIntent status will always be STPSetupIntentStatusSucceeded.
 */
- (void)confirmSetupIntent:(STPSetupIntentConfirmParams *)setupIntentConfirmParams
 withAuthenticationContext:(id<STPAuthenticationContext>)authenticationContext
                completion:(STPPaymentHandlerActionSetupIntentCompletionBlock)completion
NS_SWIFT_NAME(confirmSetupIntent(withParams:authenticationContext:completion:));

/**
 Handles any `nextAction` required to authenticate the SetupIntent.

 Call this method if you are confirming the SetupIntent on your backend and get a status of requires_action.

 @param setupIntentClientSecret The client secret of the SetupIntent to handle next actions for.
 @param authenticationContext The authentication context used to authenticate the SetupIntent.
 @param returnURL An optional URL to redirect your customer back to after they authenticate or cancel in a webview. This should match the returnURL you specified during SetupIntent confirmation.
 @param completion The completion block. If the status returned is `STPPaymentHandlerActionStatusSucceeded`, the SetupIntent status will always be  STPSetupIntentStatusSucceeded.
 */
- (void)handleNextActionForSetupIntent:(NSString *)setupIntentClientSecret
             withAuthenticationContext:(id<STPAuthenticationContext>)authenticationContext
                             returnURL:(nullable NSString *)returnURL
                            completion:(STPPaymentHandlerActionSetupIntentCompletionBlock)completion
NS_SWIFT_NAME(handleNextAction(forSetupIntent:authenticationContext:returnURL:completion:));

@end

NS_ASSUME_NONNULL_END
